local function GetStringsTable()
    return TUNING.NPC_CHAT_TABLE[ type(TUNING.__NPC_LANGUAGE)=="function" and TUNING.__NPC_LANGUAGE() or TUNING.__NPC_LANGUAGE ] ["npc_item_woodlegs_tent"] or {}
end
local function Fn()
    local Fx = Class()
    --------------------------------------------
        
    function Fx:AskItem(inst)
        -- return {
        --     {name = "meatballs" , num = 1 ,slot = 1},
        --     {name = "cutgrass" , num = 3 ,slot = 2},
        --     {name = "goldnugget" , num = 7,slot = 3},
        --     {name = "twigs" ,  num = 4, slot = 4},
        -- }
        local foods = { "bonestew","meatballs","bonestew","meatballs","bonestew","meatballs","honeyham" ,"frogglebunwich","monsterlasagna" }
        local weapons = {"oar","oar","torch","oar","oar","torch","oar","oar","oar","oar","oar","oar","oar_driftwood","oar","fishingrod","oceanfishingrod"}
        local items = {"razor","bandage","lifeinjector","healingsalve","reviver"}
        local boat_items = {"boat_item","boatpatch","boat_item","boatpatch","boat_item","boatpatch","boat_item","boatpatch","anchor_item","steeringwheel_item","mast_item"}

        local ret_food = inst.npc_base_lib:GetRandom(foods)
        local food_num = math.random(4)
        
        local ret_weapon = inst.npc_base_lib:GetRandom(weapons)
        
        local ret_item = inst.npc_base_lib:GetRandom(items)
        local item_num = 1
        if inst.npc_base_lib:Get_Item_Stack_Max_Num(ret_item) > 1 then
            item_num = math.random(3)
        end

        local ret_boat_item = inst.npc_base_lib:GetRandom(boat_items)
        local boat_item_num = 1
        if inst.npc_base_lib:Get_Item_Stack_Max_Num(ret_boat_item) > 1 then
            boat_item_num = math.random(5)
        end

        return{
            {slot = 1 , name = ret_food , num = food_num},
            {slot = 2 , name = ret_weapon , num = 1},
            {slot = 3 , name = ret_item , num = item_num},
            {slot = 4 , name = ret_boat_item , num = boat_item_num}
        }
    end

    local function Add_Woodlegs_Attacked_Event(Woodlegs,inst)
        -----------------------------------------------
        ---- 被打次数累计到一个数值后，爆出金币。
        ---- 这个数值会在爆出金币后增加。
        ---- 必须是玩家亲手打。
        ---- 名字会跟着变。
        ---- 相关参数储存在 tent（inst） 里。
        ---- 爆金币后会短暂无敌状态。
        -----------------------------------------------
        Woodlegs:ListenForEvent("attacked",function(_,_table)
            if _table and _table.attacker and _table.attacker:HasTag("player") and _table.attacker.components.playercontroller then
                local attacked_num = Woodlegs.npc_everything_data:Add("attacked.num",1)
                
                local attacked_num_base_coin = 3000

                local attacked_num_coin = inst.npc_everything_data:Add("attacked.max_coin_num",0)
                if attacked_num_coin == 0 then
                    attacked_num_coin = inst.npc_everything_data:Add("attacked.max_coin_num",attacked_num_base_coin)
                end
                if TUNING.NPC_MOD_TEST_DEBUG then
                    attacked_num_coin = 5
                end

                if  attacked_num == 1 or attacked_num%8 == 0 and attacked_num ~= attacked_num_coin then
                    Woodlegs:DoTaskInTime(0.3,function()
                        Woodlegs.npc_base_lib:Say(GetStringsTable()["Waiting.attacked"],true)
                        if inst.npc_everything_data:Add("attacked.max_coin_num",0) > attacked_num_base_coin then
                            Woodlegs.components.named:SetName(GetStringsTable()["Waiting.attacke_name.2"])
                        else
                            Woodlegs.components.named:SetName(GetStringsTable()["Waiting.attacke_name"])
                        end
                        Woodlegs.npc_base_lib:FaceToInst(_table.attacker)                 
                    end)
                end

                if Woodlegs.npc_everything_data:Add("attacked.num",0) > attacked_num_coin then
                    Woodlegs.npc_everything_data:Set("attacked.num",0)
                    Woodlegs.npc_base_lib:Throw_Out_Items({
                        name = "npc_item_goldnugget_coin",
                        num = math.random(3,8),
                        range = 4,
                        height = 5,
                        random_height = true,
                        -- fn = function(item)
                        --     item.AnimState:PlayAnimation("idle")
                        -- end
                    })
                    Woodlegs.npc_base_lib:Say(GetStringsTable()["Waiting.attacked.2"])
                    Woodlegs.components.named:SetName(GetStringsTable()["Waiting.attacke_name.2"])
                    ----------- 
                    -- 处理被打次数,每次累加 100
                    print( "info : attacked.max_coin_num",inst.npc_everything_data:Add("attacked.max_coin_num",200) )

                    Woodlegs:AddTag("INLIMBO")
                    Woodlegs:DoTaskInTime(10,function() Woodlegs:RemoveTag("INLIMBO") end)
                end
            end
            -- Woodlegs.components.inspectable:SetDescription(GetStringsTable()["Waiting.inspect"])
        end)
    end

    local function Create_Box(inst,day)
        -- npc_item_woodlegs_treasure_box
        local pt = inst.npc_base_lib:GetSpawnPoint(inst,2.5) or inst.npc_base_lib:GetSpawnPoint(inst,1.5) or inst.npc_base_lib:GetSpawnPoint(inst,0.5) or Vector3(inst.Transform:GetWorldPosition())
        local box = SpawnPrefab("npc_item_woodlegs_treasure_box")
        box.Transform:SetPosition(pt.x, 0, pt.z)
        box:DoTaskInTime(0.5,function()
            local foods_name = {"bullkelp_root","kelp","cave_banana","fishmeat","barnacle","barnacle","barnacle","npc_item_treasure_map"}

            local items_name = {"npc_item_cards_experience_pack","npc_item_treasure_map","npc_item_bottle_with_coin",
                            "npc_item_rainbow_horn","npc_item_pigman_arena_spell_coin","dug_trap_starfish","palmcone_seed","dug_bananabush",
                            "driftwood_log","treegrowthsolution","chum","malbatross_feather","malbatross_feathered_weave","cookiecuttershell",
                            "slurtle_shellpieces","gnarwail_horn"}

            local equiptments_name = {"nightsword","batbat","npc_item_wortox_hambat","waterplant_bomb","fishingnet","oar_monkey",
                            "trident","glasscutter","nightstick","malbatross_beak","moonglassaxe","alterguardianhat","monkey_mediumhat","monkey_smallhat",
                            "polly_rogershat"}
                            
            local ret_foods_name = {}
            local ret_items_name = {}
            local ret_equiptments_name = {}
            for i = 1, 5, 1 do
                table.insert(ret_foods_name,inst.npc_base_lib:GetRandom(foods_name))
                table.insert(ret_items_name,inst.npc_base_lib:GetRandom(items_name))
                if i <= 3 then
                    table.insert(ret_equiptments_name,inst.npc_base_lib:GetRandom(equiptments_name))
                end
            end

            for k, name in pairs(ret_foods_name) do
                local item = SpawnPrefab(name) or SpawnPrefab("log")
                if item.components.stackable then
                    local num = math.ceil( (item.components.stackable.maxsize/4)*day )
                    local max_num = item.components.stackable.maxsize
                    if max_num > 70 then --- 开了叠堆上限MOD的人得到更少。
                        max_num = 10
                    end
                    num = math.clamp(num,1,max_num)
                    item.components.stackable.stacksize = num
                end
                box.components.container:GiveItem(item)
            end

            for k, name in pairs(ret_items_name) do
                local item = SpawnPrefab(name) or SpawnPrefab("log")
                if item.components.stackable then
                    local num = math.ceil( (item.components.stackable.maxsize/8)*day )
                    local max_num = item.components.stackable.maxsize
                    if max_num > 70 then --- 开了叠堆上限MOD的人得到更少。
                        max_num = 10
                    end
                    num = math.clamp(num,1,max_num)
                    item.components.stackable.stacksize = num
                end
                box.components.container:GiveItem(item)
            end

            local upgrade_cmd_list = {
                ["batbat"] = {cmd = "upgrade",  type = "boss" },
                ["nightsword"] = {cmd = "upgrade",  type = "bloody" }
            }

            for k, name in pairs(ret_equiptments_name) do
                local item = SpawnPrefab(name) or SpawnPrefab("log")
                box.components.container:GiveItem(item)
                if upgrade_cmd_list[name] then
                    item:PushEvent(upgrade_cmd_list[name].cmd,upgrade_cmd_list[name].type)
                    inst.npc_base_lib:Change_Item_Skin(item)
                end
            end

            if math.random(100) < 20 then
                local gold_coin = SpawnPrefab("npc_item_goldnugget_coin")
                -- gold_coin.components.stackable.stacksize = math.ceil(day/2)
                box.components.container:GiveItem(gold_coin)
            else
                local cards_pack = SpawnPrefab("npc_item_cards_experience_pack")
                box.components.container:GiveItem(cards_pack)
            end

        end)
        inst.npc_base_lib:Announce(GetStringsTable()["box.announce"])
    end
    local function Woodlegs_Travel_Back(inst)
        if inst.npc_everything_data:Get("Travel_Back") ~= true then
            return
        end
        local day = inst.npc_everything_data:Add("Travel_Back.day",0)
        inst.npc_everything_data:Set("Travel_Back",false)
        inst.npc_everything_data:Set("Travel_Back.day",0)
        --------------------------------------------------------------------
        ---- -- 旅行奖励设置
        Create_Box(inst,day)
        print("info : Woodlegs_Travel_Back",day)
        -- print("info : Woodlegs_Travel_Back",day)
        -- print("info : Woodlegs_Travel_Back",day)
        -- print("info : Woodlegs_Travel_Back",day)
        -- print("info : Woodlegs_Travel_Back",day)

        --------------------------------------------------------------------        
    end
    function Fx:Task_Event_Init(inst)
        inst:ListenForEvent("Travel_Prepare",function(_,ondeploy)
            if ondeploy ~= true then
                inst:PushEvent("Refresh_Ask_Items")
            end
            inst.components.container.canbeopened = true
            Woodlegs_Travel_Back(inst)
        end)
        inst:ListenForEvent("Travel_Task_Start",function()
            inst:PushEvent("Refresh_Ask_Items")
            inst.components.container.canbeopened = false
            inst.npc_everything_data:Set("Travel_Task_Start",true)
        end)

        local function Create_Surrouding_Woodlegs(inst)
            local pt = inst.npc_base_lib:GetSpawnPoint(inst,1.5) or Vector3(inst.Transform:GetWorldPosition())
            local Woodlegs = SpawnPrefab("woodlegs_npc")
            inst.Surrounding_Woodlegs = Woodlegs
            Woodlegs.Transform:SetPosition(pt.x,0,pt.z)
            Woodlegs:PushEvent("player_link",inst)
            Woodlegs:AddDebuff("npc_event_woodlegs_surrounding_tent","npc_event_woodlegs_surrounding_tent")
            Woodlegs:ListenForEvent("Back_To_Door",function()
                Woodlegs:AddDebuff("npc_event_leave","npc_event_leave")
            end)
            Add_Woodlegs_Attacked_Event(Woodlegs,inst)
            Woodlegs:DoTaskInTime(1,function()
                Woodlegs.components.inspectable:SetDescription(GetStringsTable()["Waiting.inspect"])                
            end)
        end
        local function Refresh_Woodlegs_Task_Start(inst)
            -- print("info : Refresh_Woodlegs_Task_Start",0,inst.Surrounding_Woodlegs)
            if inst.Surrounding_Woodlegs and inst.Surrounding_Woodlegs:IsValid() then
                return
            end
            -- print("info : Refresh_Woodlegs_Task_Start",1)

            if inst.npc_everything_data:Get("Travelling") == true then
                return
            end
            -- print("info : Refresh_Woodlegs_Task_Start",2)

            if inst._Create_Surrounding_Woodlegs_Task then
                inst._Create_Surrounding_Woodlegs_Task:Cancel()
                inst._Create_Surrounding_Woodlegs_Task = nil
            end
            -- print("info : Refresh_Woodlegs_Task_Start",3)

            inst._Create_Surrounding_Woodlegs_Task = inst:DoPeriodicTask(5,function()
                if not inst:IsNearPlayer(TUNING.NPC_MOD_TEST_DEBUG and 3 or 25) then
                    Create_Surrouding_Woodlegs(inst)
                    inst:PushEvent("Travel_Prepare")
                end

                if inst.Surrounding_Woodlegs and inst._Create_Surrounding_Woodlegs_Task then
                    inst._Create_Surrounding_Woodlegs_Task:Cancel()
                    inst._Create_Surrounding_Woodlegs_Task = nil
                end

            end)
        end
        inst:DoTaskInTime(0.5,function()  ----------------- 加载的时候创建任务
            Refresh_Woodlegs_Task_Start(inst)
            if inst.npc_everything_data:Get("Travelling") then
                inst.components.container.canbeopened = false
            end
        end)
        ----------------------------------------------------------------------------------
        --- --- 物资准备好了，NPC出发
        inst:WatchWorldState("cycles", function()
            inst:DoTaskInTime(5,function()                        
                        -------- 任务出发
                        if inst.Surrounding_Woodlegs and  inst.Surrounding_Woodlegs:IsValid() and inst.npc_everything_data:Get("Travel_Task_Start") == true then
                            inst.npc_everything_data:Set("Travel_Task_Start",false)
                            inst.npc_everything_data:Set("Travelling",true)
                            inst.npc_everything_data:Set("Travelling.max_day",math.random(3,8))
                            if TUNING.NPC_MOD_TEST_DEBUG then
                                inst.npc_everything_data:Set("Travelling.max_day",1)
                            end
                            local Woodlegs = inst.Surrounding_Woodlegs
                            Woodlegs:DoTaskInTime(20,function()
                                Woodlegs.event_step = 100
                                Woodlegs:AddDebuff("npc_event_leave","npc_event_leave")
                                Woodlegs.npc_base_lib:Say(GetStringsTable()["Waiting.start_travel"],true)
                                Woodlegs:DoPeriodicTask(1,function()
                                    Woodlegs.npc_base_lib:Say(GetStringsTable()["Waiting.start_travel"],true)
                                end)
                                inst.Surrounding_Woodlegs = nil
                            end)                            
                        end

                        if inst.npc_everything_data:Get("Travelling") == true then
                            inst.components.container.canbeopened = false
                            local day = inst.npc_everything_data:Add("Travelling.day",1)
                            local max_day = inst.npc_everything_data:Add("Travelling.max_day",0)
                            if day > max_day then
                                inst:PushEvent("Travel_Back")
                                inst.npc_everything_data:Set("Travelling",false)
                            end
                        end

                        if inst.components.container.canbeopened == true then
                            Refresh_Woodlegs_Task_Start(inst)
                        end
            end)
        end)
        ----------------------------------------------------------------------------------
        inst:ListenForEvent("Travel_Back",function()
            inst.npc_everything_data:Set("Travel_Back",true)
            inst.npc_everything_data:Set("Travelling",false)
            inst.npc_everything_data:Add("Travel_Back.day",inst.npc_everything_data:Add("Travelling.day",0))
            inst.npc_everything_data:Set("Travelling.day",0)
            inst.Surrounding_Woodlegs = nil
            Refresh_Woodlegs_Task_Start(inst)
        end)
        ----------------------------------------------------------------------------------
        -------- sleep 相关的event
            inst:ListenForEvent("npc_sleep",function()
                inst.Light:Enable(true)
                inst.AnimState:PlayAnimation("sleep_loop",true)
            end)
            inst:ListenForEvent("npc_wakeup",function()
                inst.Light:Enable(false)   
                inst.AnimState:PlayAnimation("idle",true)
            end)
        ----------------------------------------------------------------------------------
    end


    function Fx:Task_Event_Init_Item(inst)
        -----------------------------------------------------------------------------
        -- -- -- 如果被放置回绚丽之门
            local function Create_Wating_Woodlegs(inst)
                if inst.npc_woodlegs ~= nil then
                    inst.npc_woodlegs:Remove()
                end
                local npc = SpawnPrefab("woodlegs_npc")
                npc.Ready = true
                inst.npc_woodlegs = npc
                npc:AddTag("Wating_Woodlegs")
                local pt = inst.npc_base_lib:GetSpawnPoint(inst,1) or Vector3(inst.Transform:GetWorldPosition())
                npc.Transform:SetPosition(pt.x, pt.y, pt.z)
                npc:ListenForEvent("onpickup",function()
                    if npc._talk_task then
                        npc._talk_task:Cancel()
                    end
                    npc.npc_base_lib:Say(GetStringsTable()["Waiting.onpickup"])
                    npc:DoTaskInTime(2,function()
                        npc:AddDebuff("npc_event_leave", "npc_event_leave")
                    end)

                end)
                npc:AddComponent("playerprox")
                npc.components.playerprox:SetDist(10, 13)
                npc.components.playerprox:SetOnPlayerNear(function()
                    local player = npc:GetNearestPlayer()
                    npc.npc_base_lib:FaceToInst(player)
                    npc.npc_base_lib:Say(GetStringsTable()["Waiting.player"],true)                        
                    npc._talk_task = npc:DoPeriodicTask(4,function()
                        local player2 = npc:GetNearestPlayer()
                        npc.npc_base_lib:FaceToInst(player2)
                        npc.npc_base_lib:Say(GetStringsTable()["Waiting.player"],true)                        
                    end)
                end)
                npc.components.playerprox:SetOnPlayerFar(function()
                    if npc._talk_task then
                        npc._talk_task:Cancel()
                        npc._talk_task = nil
                    end
                end)
                Add_Woodlegs_Attacked_Event(npc,inst)


            end
            inst:ListenForEvent("Back_To_Door",function()
                print(inst,"Back_To_Door")
                inst.npc_everything_data:Set("Back_To_Door",true)
                if inst.Surrounding_Woodlegs then
                    inst.Surrounding_Woodlegs:PushEvent("Back_To_Door")
                    inst.Surrounding_Woodlegs = nil
                end
            end)
            inst:ListenForEvent("onpickup",function()
                print(inst,"onpickup")
                inst.npc_everything_data:Set("Back_To_Door",false)
                if inst.npc_woodlegs then
                    inst.npc_woodlegs:PushEvent("onpickup")
                end
            end)
            inst:ListenForEvent("Create_Wating_Woodlegs",Create_Wating_Woodlegs)

            local function Create_Wating_Woodlegs_Task_Fn(inst)
                inst:DoTaskInTime(5,function()
                    if inst.npc_everything_data:Get("Back_To_Door") == true and inst.npc_woodlegs == nil and inst:IsNearPlayer(TUNING.NPC_MOD_TEST_DEBUG and 3 or 25) == false then
                        inst:PushEvent("Create_Wating_Woodlegs")
                    end
                end)
            end
            inst:WatchWorldState("cycles", function() Create_Wating_Woodlegs_Task_Fn(inst) end)
            inst:DoTaskInTime(5,Create_Wating_Woodlegs_Task_Fn) ------------- 载入的时候检测并刷出NPC
        -----------------------------------------------------------------------------

    end

    return Fx
end

return Fn